/**
  ETFRoot project, Anyang Normal University && IMP-CAS
  \class ETFTstop4
  \brief a plastic scintillator (square) plate with its four corners each coupled
  with a PMT, usually for cosmic-ray tests
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2022-04-25
  \date 2021-04-25 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2022-04-25   <td>Asia Sun    <td>file created                  </tr>
  </table>

  \copyright Copyright (c) 2021 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/
#include <cstring>
#include <TClonesArray.h>
#include <TGraph.h>
#include "ETFTstop4.h"
#include "ETFDetectorManager.h"
#include "ETFHPTDCChannel.h"
#include "ETFPlaHit.h"
#include "ETFMath.h"
#include "ETFMsg.h"
#include "ETFYaml.h"
#include "ETFParaManager.h"

ClassImp(ETFTstop4);

static const double DEGREE = ETFMath::DEGREE();

ETFTstop4::ETFTstop4(const char *name) : ETFTimer(name){
  ETFParaManager *pm = ETFParaManager::Instance();
  const YAML::Node &chIdConfig = (*pm->GetChIdPara())[name];
  const int chId0 = chIdConfig.as<int>();
  // assign channel ids for the 4*2 channels //
  // i[0-8] -> i/2: PMT, i%2: 0->V, 1->H
  for(int i = 0; i < 8; i++) SetChIdMap(chId0+i, fDetId + (i<<8));
  // pass user trig bound parameters //
  const YAML::Node &trigBConfig = (*pm->GetMisPara())["tstopTaLTrigB"];
  if(trigBConfig){
    fTrigLB = trigBConfig[0].as<double>();
    fTrigHB = trigBConfig[1].as<double>();
  } // end if

  fHits = new TClonesArray("ETFPlaHit");
  fHits->SetName(name);
} // end ctor

// add the data channel to the detector
void ETFTstop4::Assign(const ETFHPTDCChannel *ch){
  int uid = ETFDetectorManager::Instance()->GetUID(ch->GetChannelId());
  if(fDetId != (uid & 0xFF)) ETFMsg::Error("ETFTstop4", "Assign: not from this detector.");
  int idvh = uid>>8 & 0x7;
  AddHit(ch, idvh);
} // end member function Assign

void ETFTstop4::AddHit(const ETFHPTDCChannel *ch, int idvh){
  ETFPlaHit *hit = nullptr;
  const int stripId = idvh / 4; // 2 PMTs of a strip are on the same side of the PL plate
  for(auto p : *fHits){
    ETFPlaHit *h = dynamic_cast<ETFPlaHit *>(p);
    if(stripId == h->GetStripId()){ // old strip
      hit = h; continue;
    } // end if
  } // end for
  if(!hit){ // the strip of this hit has not been registered
    hit = dynamic_cast<ETFPlaHit *>(fHits->ConstructedAt(fHits->GetEntries()));
    hit->Initialize();
    hit->SetStripId(stripId);
    hit->SetLength(700.);
    double pos[3]{};
    hit->SetPosition(pos);
    hit->SetDelay(fDelay);
    TransformToLabRef(hit);
  } // end if(hit is nullptr)
  hit->SetDataChannel(ch, idvh%4); // idvh%4: udvh
} // end member function AddHit

double ETFTstop4::GetTime() const{
  const int nh = fHits->GetEntries();
  if(!nh) ETFMsg::Error("ETFStart", "GetTime: No hits in Tstop4");
  if(1 == nh) ETFMsg::Error("ETFStart", "GetTime: only 1 strip hits found in Tstop4");
  const double t0 = dynamic_cast<ETFPlaHit *>(fHits->At(0))->GetTime();
  const double t1 = dynamic_cast<ETFPlaHit *>(fHits->At(1))->GetTime();
  return (t0+t1)/2.;
} // end member function GetTime

// return the fired status of Tstop
int ETFTstop4::GetFiredStatus() const{
  const int nh = fHits->GetEntries();
  if(!nh) return -2;
  if(1 == nh) return -1;
  const int s0 = dynamic_cast<ETFPlaHit *>(fHits->At(0))->GetFiredStatus();
  const int s1 = dynamic_cast<ETFPlaHit *>(fHits->At(1))->GetFiredStatus();
  const int sta = s0+s1;
  if(8 == sta) return 4;
  if(4 == sta) return 5;
  return sta;
} // end member function GetFiredStatus

// add strip to fGDumb
void ETFTstop4::ConstructGraph(){
  if(fGDumb->GetN()) return; // has called

  fGDumb->SetMarkerStyle(28);
  fGDumb->SetMarkerColor(30); // gray
  double p[3]{};
  TransformToLabRef(p);
  fGDumb->SetPoint(0, p[2], p[0]);
} // end member function ConstructGraph

void ETFTstop4::DrawHits(){
  for(const auto &p : *fHits) if(p){
    ETFPlaHit *h = dynamic_cast<ETFPlaHit *>(p);
    h->GetGHit()->SetMarkerStyle(21);
    if(h->GetFiredStatus() == 4) h->Draw();
  } // end for and if
} // end member function DrawHits
